package uform.model.core;

import uform.model.cell.ArrayCell;
import uform.model.cell.ValueCell;
import uform.model.value.FloatType;
import uform.model.value.StringType;
import utest.Assert;
import uform.model.core.Schema;

class TestModel extends Test
{
	public function testGet()
	{
		var schema = new Schema();
		var model = new Model(schema);
		
		// invalid path
		Assert.raises(callback(model.get, "*"), Dynamic);
		Assert.raises(callback(model.get, "addresses[-1]"), Dynamic);
		
		// path to unexistant fields
		Assert.raises(callback(model.get, "name"), Dynamic);
		Assert.raises(callback(model.get, "names[2]"), Dynamic);
		Assert.raises(callback(model.get, "addresses[1].street"), Dynamic);
		
		schema.addCell("name", new ValueCell(new StringType(), true));
		Assert.isNull(model.get("name"));
		Reflect.setField(model.data, "name", "franco");
		Assert.equals("franco", model.get("name"));
		
		schema.addCell("names", new ArrayCell(new StringType()));
		Assert.isNull(model.get("names"));
		Reflect.setField(model.data, "names", []);
		
		Assert.is(model.get("names"), Array);
		Assert.isNull(model.get("names[0]"));
		Assert.isNull(model.get("names[1]"));
		
		Reflect.setField(model.data, "names", ["a", "b"]);
		Assert.equals("a", model.get("names[0]"));
		Assert.equals("b", model.get("names[1]"));
		
		var addressSchema = new Schema();
		addressSchema.addCell("street", new ValueCell(new StringType(), true));
		schema.addCell("addresses", new ArrayCell(addressSchema));
		
		Assert.isNull(model.get("addresses[1].street"));
		
		Reflect.setField(model.data, "addresses", [ { street : "a" }, { street : "b" } ]);
		
		Assert.equals("a", model.get("addresses[0].street"));
		Assert.equals("b", model.get("addresses[1].street"));
	}
	
	public function testSet()
	{
		var schema = new Schema();
		var model = new Model(schema);
		
		// invalid path
		Assert.raises(function() model.set("*", "x"), Dynamic);
		Assert.raises(function() model.set("addresses[-1]", "x"), Dynamic);
		
		// path to unexistant fields
		Assert.raises(function() model.set("name", "x"), Dynamic);
		Assert.raises(function() model.set("names[2]", "x"), Dynamic);
		Assert.raises(function() model.set("addresses[1].street", "x"), Dynamic);
		
		schema.addCell("name", new ValueCell(new StringType(), true));
		schema.addCell("names", new ArrayCell(new StringType()));
		var addressSchema = new Schema();
		addressSchema.addCell("street", new ValueCell(new StringType(), true));
		schema.addCell("addresses", new ArrayCell(addressSchema));
		
		model.set("name", "franco");
		Assert.equals("franco", model.data.name);
		model.set("names", []);
		Assert.same([], model.data.names);
		model.set("names[1]", "franco");
		Assert.same([null, "franco"], model.data.names);
		model.set("names", null);
		model.set("names[1]", "franco");
		Assert.same([null, "franco"], model.data.names);
		model.set("names[0]", "haxe");
		Assert.same(["haxe", "franco"], model.data.names);
		model.set("addresses[1].street", "a");
		Assert.equals("a", model.data.addresses[1].street);
		
		assertValidation(model.validate(), false);
		model.set("addresses[0].street", "b");
		assertValidation(model.validate(), true);
	}
	
	public function testSetString()
	{
		var schema = new Schema();
		var model = new Model(schema);
		
		schema.addCell("age", new ValueCell(new FloatType(), true));
		schema.addCell("points", new ArrayCell(new FloatType()));
		var seasonSchema = new Schema();
		seasonSchema.addCell("year", new ValueCell(new FloatType(), true));
		schema.addCell("seasons", new ArrayCell(seasonSchema));
		
		model.setString("age", "38");
		Assert.equals(38, model.data.age);
		model.setString("points", "[0.1,0.2]");
		Assert.same([0.1, 0.2], model.data.points);
		
		model.setString("points", "[]");
		Assert.same([], model.data.points);
		
		model.setString("points[1]", "0.2");
		Assert.same([null, 0.2], model.data.points);
		model.setString("points", null);
		model.setString("points[1]", "0.2");
		Assert.same([null, 0.2], model.data.points);
		model.setString("points[0]", "0.1");
		Assert.same([0.1, 0.2], model.data.points);
		model.setString("seasons[1].year", "2010");
		Assert.equals(2010, model.data.seasons[1].year);
		
		assertValidation(model.validate(), false);
		model.setString("seasons[0].year", "2009");
		assertValidation(model.validate(), true);
	}
	
	public function new();
}